﻿// This file is part of Code4Public (http://code4public.codeplex.com)
// Copyright 2011 Sina Iravanian - <sina@sinairv.com>
//
// This source file(s) may be redistributed, altered and customized
// by any means PROVIDING the authors name and all copyright
// notices remain intact.
// THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED. USE IT AT YOUR OWN RISK. THE AUTHOR ACCEPTS NO
// LIABILITY FOR ANY DATA DAMAGE/LOSS THAT THIS PRODUCT MAY CAUSE.
// ------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Code4Public.Languages.Error
{
    #region Abstract Class ParsingErrorItemBase
    public abstract class ParsingErrorItemBase
    {
        #region Properties
        public bool IsRecoverable { get; protected set; }
        protected string Argument1 { get; set; }
        protected string Argument2 { get; set; }
        #endregion

        #region Get*Error Static Methods to Create Different Error Types
        public static ParsingErrorItemBase GetFileNotFoundError(string fileName)
        {
            return new DocumentParsingErrorItem(DocumentErrorType.FileNotFound) { Argument1 = fileName };
        }

        public static ParsingErrorItemBase GetMalformedXMLFileError(string fileName)
        {
            return new DocumentParsingErrorItem(DocumentErrorType.MalformedXMLDocument) { Argument1 = fileName };
        }
        
        public static ParsingErrorItemBase GetGeneralExceptionError(string exception)
        {
            return new DocumentParsingErrorItem(DocumentErrorType.UnknownException) { Argument1 = exception };
        }

        public static ParsingErrorItemBase GetInvalidRootError(string expectedRoot, string foundRoot)
        {
            return new DocumentParsingErrorItem(DocumentErrorType.InvalidRoot) { Argument1 = expectedRoot, Argument2 = foundRoot };
        }

        public static ParsingErrorItemBase GetExpectedTagButFoundTagError(string expectedTag, string foundTag)
        {
            return new ElementParsingErrorItem(ElementErrorType.ExpectedTagNameButFound) { LanguageName = "", XMLElementName = "", Argument1 = expectedTag, Argument2 = foundTag };
        }

        public static ParsingErrorItemBase GetUnknownAttrNameError(string langName, string xmlElement, string attrName)
        {
            return new ElementParsingErrorItem(ElementErrorType.IgnoringUnknownAttributeName) { LanguageName = langName, XMLElementName = xmlElement, Argument1 = attrName };
        }

        public static ParsingErrorItemBase GetAttrMissedError(string langName, string xmlElement, string attrNames)
        {
            return new ElementParsingErrorItem(ElementErrorType.AttributeIsMissed) { LanguageName = langName, XMLElementName = xmlElement, Argument1 = attrNames };
        }

        public static ParsingErrorItemBase GetUnknownTagError(string langName, string xmlElement, string tagName)
        {
            return new ElementParsingErrorItem(ElementErrorType.IgnoringUnknownTag) { LanguageName = langName, XMLElementName = xmlElement, Argument1 = tagName };
        }

        public static ParsingErrorItemBase GetWordAlreadyAddedError(string langName, string xmlElement, string word)
        {
            return new ElementParsingErrorItem(ElementErrorType.WordIsAlreadyAdded) { LanguageName = langName, XMLElementName = xmlElement, Argument1 = word };
        }
        #endregion
    }
    #endregion

    #region Class DocumentParsingErrorItem
    public class DocumentParsingErrorItem : ParsingErrorItemBase
    {
        public DocumentErrorType ErrorType { get; protected set; }
        
        public DocumentParsingErrorItem(DocumentErrorType errType)
        {
            IsRecoverable = false;
            this.ErrorType = errType;
        }

        public override string ToString()
        {
            // TODO use string tables to return a description
            string errDesc = "";
            switch (ErrorType)
            {
                case DocumentErrorType.FileNotFound:
                    errDesc = "File Not Found: " + Argument1;
                    break;
                case DocumentErrorType.MalformedXMLDocument:
                    errDesc = "Malformed XML Document: " + Argument1;
                    break;
                case DocumentErrorType.UnknownException:
                    errDesc = "Unknown Exception occurred: " + Argument1;
                    break;
                case DocumentErrorType.InvalidRoot:
                    errDesc = String.Format("Invalid Root Tag, Expected <{0}> but found <{1}>", Argument1, Argument2);
                    break;
            }

            return string.Format("{0} Error - Type: {1} - Desc: {2}",
               (IsRecoverable ? "" : "Non") + "Recoverable", ErrorType.ToString(), errDesc);
   
        }
    }

    #endregion

    #region Class ElementParsingErrorItem
    public class ElementParsingErrorItem : ParsingErrorItemBase
    {
        public ElementErrorType ErrorType { get; protected set; }
        public string LanguageName { get; set; }
        public string XMLElementName { get; set; }

        public ElementParsingErrorItem(ElementErrorType errType)
        {
            ErrorType = errType;
            IsRecoverable = true;
        }

        public override string ToString()
        {
            // TODO use string tables to return a description
            string errDesc = "";
            switch (ErrorType)
            {
                case ElementErrorType.ExpectedTagNameButFound:
                    errDesc = String.Format("Expected tag <{0}> but found <{1}>", Argument1, Argument2);
                    break;
                case ElementErrorType.IgnoringUnknownTag:
                    errDesc = String.Format("Ignoring unknown tag <{0}>", Argument1);
                    break;
                case ElementErrorType.IgnoringUnknownAttributeName:
                    errDesc = String.Format("Ignoring unknown attribute: {0}", Argument1);
                    break;
                case ElementErrorType.AttributeIsMissed:
                    errDesc = String.Format("Ignoring tag <{0}> because following attributes are missed: {1}", XMLElementName, Argument1);
                    break;
                case ElementErrorType.WordIsAlreadyAdded:
                    errDesc = String.Format("Word is already added: {0}", Argument1);
                    break;
                default:
                    break;
            }

            return string.Format("{0} Error - Language: {1} - ElementName: {2} - ErrType: {3} - Desc: {4}",
                (IsRecoverable ? "" : "Non") + "Recoverable", LanguageName, XMLElementName, ErrorType.ToString(), errDesc);
        }
    }

    #endregion

    #region DocumentErrorType, ElementErrorType enums
    public enum DocumentErrorType
    {
        FileNotFound,
        MalformedXMLDocument,
        UnknownException,
        InvalidRoot
    }

    public enum ElementErrorType
    {
        ExpectedTagNameButFound,
        IgnoringUnknownTag,
        IgnoringUnknownAttributeName,
        AttributeIsMissed,
        WordIsAlreadyAdded
    }
    #endregion
}
